using System;
using System.Collections;
using System.Globalization;
using System.Text;
using System.Threading;
using System.Web.UI;
using System.Web.UI.WebControls;
using Sedna.Core.Controller;
using Sedna.Core.Controller.Configurations;
using Sedna.Core.Controls.Support;
using Sedna.Core.Controls.Support.Javascript;
using Sedna.Core.Globalization;
using Nullables;

namespace Sedna.Core.Controls
{
	[ValidationProperty("Text")]
	public class DatePicker : BaseControl, INamingContainer, IClientScriptingControl, IValueProvider
    {
        #region Fields
	    
        protected TextBox textBox = new TextBox("textBox");
	    protected Hidden hidden = new Hidden("hidden");
		protected System.Web.UI.WebControls.Label literalButton = new System.Web.UI.WebControls.Label();

		private TimeSpan timeOfDay = TimeSpan.Zero;
		
		private Boolean  selectHoliday = true;

        private bool originalVisible;

		public event EventHandler TextChanged;

        #endregion

        #region Properties

        public override bool Enabled
		{
			get { return base.Enabled; }
			set
			{
				base.Enabled = value;
                textBox.Enabled = value;
			}
		}

        public override bool Visible
        {
            get { return base.Visible; }
            set
            {
                base.Visible = value;
                textBox.Visible = value;
            }
        }
	    
	    
		public bool SelectHoliday
		{
			get
			{
				return selectHoliday;
			}
			
			set
			{
				selectHoliday = value;
			}
		}

		/// <summary>
		/// Gets or sets selected date (DateTime), or null if no date selected.
		/// </summary>
		public object Value
		{
			get
			{
				EnsureChildControls();
				try
				{
					DateTime date=DateTime.Parse(Text, Configuration.PrincipalWrapper.Culture.DateTimeFormat, DateTimeStyles.AllowWhiteSpaces);
					return date.Date.Add(timeOfDay);
				}
				catch { /* igniore */ }
				return ((IDatePickerConfiguration)configuration).AllowNull? null : (object)DateTime.Today;
			}

			set
			{
				EnsureChildControls();
			    
				if (value == null)
				{
					Text = "";
					return;
				}

                DateTime dt;

                if (value is NullableDateTime)
                {
                    if ( ((NullableDateTime)value).HasValue )
                        dt = ((NullableDateTime)value).Value;
                    else
                    {
                        Text = "";
                        return;
                    }
                }
                else
                    dt = Convert.ToDateTime(value);

                Text = (dt).Date.ToString(Configuration.PrincipalWrapper.Culture.DateTimeFormat.ShortDatePattern, Configuration.PrincipalWrapper.Culture.DateTimeFormat);
			}
		}

		public TimeSpan TimeOfDay
		{
			get { return timeOfDay; }
			set { timeOfDay = value; }
		}

		public string Text 
		{
			get
			{
				EnsureChildControls();
                textBox.Text = hidden.Value;
				return textBox.Text;
			}

			set
			{
				EnsureChildControls();                
				textBox.Text = value;
                hidden.Value = textBox.Text;
			}
		}

/*
		public Unit TextWidth 
		{
			get
			{
				EnsureChildControls();
				return textBox.Width;
			}
			set
			{
				EnsureChildControls();
				textBox.Width=value;
			}
		}
*/

		protected override HtmlTextWriterTag TagKey
		{
			get { return HtmlTextWriterTag.Table; }
        }

        #endregion
	    
        public DatePicker() :base()
		{
		    //TODO: refactor to take from config
            javascriptClass = "DatePicker";
			configurationId = "configuration.default.DatePicker";
			Initialize();
		}

		public DatePicker(string id) :this()
		{
			this.ID = id;
//			this.datePickerType = controlType;
			Initialize();
		}

		public DatePicker(IConfiguration configuration) : base(configuration)
		{
			Initialize();
		}

	    protected override void LoadViewState(object savedState)
	    {
            base.LoadViewState(savedState);
	        
	        if (!Enabled && String.IsNullOrEmpty(Text))
	        {
	            String text = ViewState["dtp.text"] as String;
	            
	            Text = text == null ? String.Empty : text;
	        }
	    }

	    protected override object SaveViewState()
	    {
            if (Enabled)
            {
                ViewState.Remove("dtp.text");
            }
            else
            {
                ViewState.Add("dtp.text", Text);
            }
	        
	        object obj = base.SaveViewState();
	        	        	        
	        return obj;
	    }

	    private void Initialize()
		{
			this.textBox.TextChanged+=new EventHandler(OnTextChanged);
			Width=Unit.Pixel(120);
			literalButton.Text="<input type=\"button\" value=\"#\" class=\"btnsearch\" >";
		}

	    protected override void OnLoad(EventArgs e)
	    {
	        base.OnLoad(e);

            # region Visibility

            originalVisible = Visible;
	        
            if (Configuration.VisibleBindPath != null)
                Visible = true; // To reach the OnPreRender method and analyze visibility in the Bind method

            # endregion
        }

	    private void OnTextChanged(object sender, EventArgs e)
		{
			if (TextChanged!=null)
			{
				this.TextChanged.Invoke(sender, e);					
			}
		}

		protected override void Build()
		{			
            IDatePickerConfiguration datePickerConfiguration = (IDatePickerConfiguration) configuration;
            timeOfDay = datePickerConfiguration.TimeOfDay;
            ClientScriptingEnabled = datePickerConfiguration.ClientScriptingEnabled;
            ClientVariable = datePickerConfiguration.ClientVariable;

		}

		protected override void CreateChildControls() 
		{

			TableRow row=new TableRow();
			Controls.Add(row);

			TableCell textBoxCell=new TableCell();
			textBoxCell.Width=Unit.Percentage(100);
			row.Controls.Add(textBoxCell);

			textBoxCell.Controls.Add(textBox);
			textBox.Width = Unit.Percentage(100);
            textBox.ReadOnly = !((IDatePickerConfiguration)configuration).AllowManualEnter;

			TableCell spacerCell=new TableCell();
			spacerCell.Controls.Add(new System.Web.UI.LiteralControl("&nbsp;"));
			spacerCell.Width=Unit.Percentage(0);
			row.Controls.Add(spacerCell);

			TableCell buttonCell=new TableCell();
			buttonCell.Width=Unit.Percentage(0);
			row.Controls.Add(buttonCell);

			buttonCell.Controls.Add(literalButton);
		    
		    TableCell hiddenCell = new TableCell();
            hiddenCell.Width = Unit.Percentage(0);
            row.Controls.Add(hiddenCell);

            hiddenCell.Controls.Add(hidden);

            
        }

		protected override void AddAttributesToRender(HtmlTextWriter writer)
		{
			base.AddAttributesToRender(writer);
			writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
			writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
			writer.AddAttribute(HtmlTextWriterAttribute.Align, "left");
		}
	    
		protected override void OnPreRender(EventArgs e)
		{
			
			base.OnPreRender(e);
			
			if (!Page.ClientScript.IsClientScriptBlockRegistered("coreims.calendar"))
			{
				Page.ClientScript.RegisterClientScriptBlock(typeof(DatePicker), "coreims.calendar", GenerateCalendarHtml());
			}
            String clearButtonVisible = ((IDatePickerConfiguration) configuration).AllowNull.ToString().ToLower();
            literalButton.Text = "<a href=\"#\"><img class=\"noborder\" align=\"absmiddle\" src=\"" + ImageManager.Relate(this, "calbtn.gif") + "\" onclick=\"if(self.gfPop){gfPop.setSelectHoliday(" + JavascriptUtil.ToScriptObject(selectHoliday) + ");gfPop.fPopCalendar(document.getElementById(\'" + textBox.ClientID + "\'), document.getElementById(\'" + hidden.ClientID + "\'),null, null, this, null, " + clearButtonVisible + ");return false;}\" " + (Enabled ? String.Empty : "disabled") + "></a>";

			if (ClientScriptingEnabled)
			{
//				EnableClientScripting();
			    DeclareScriptVariable();
			}
		}

		private string GenerateCalendarHtml()
		{
			StringBuilder buffer=new StringBuilder(300);
			buffer.Append("<!-- Calendar iframe -->");
			buffer.Append("<iframe style=\"z-index: 999; left: -500px; visibility: visible; position: absolute; top: 0px\" ");
			buffer.AppendFormat(" name=\"{0}\"", "gToday:normal");
			buffer.AppendFormat(" id=\"{0}\"", "gToday:normal");
			buffer.AppendFormat(" src=\"{0}\"", ResolveUrl("~/Core/pages/Controls/DatePicker/ipopeng.htm"));
			buffer.Append(" frameBorder=\"0\" width=\"1\" scrolling=\"no\" height=\"1\"></iframe>");	

			return buffer.ToString();
		}

//		private void EnableClientScripting()
//		{
//			textBox.ClientScriptingEnabled=true;
//			ControlUtil.EnsureIdAttribute(literalButton);
//			ControlUtil.EnsureIdAttribute(this);
//
//
//            JavascriptController.Current.DeclareClass("DatePicker");
//            JavascriptController.Current.DeclareObject(ClientVariable, "DatePicker", JavascriptUtil.EncloseWithQuotes(ClientID), textBox.ClientVariable, JavascriptUtil.EncloseWithQuotes(literalButton.ClientID));
//		}
//

	    protected override void DeclareScriptVariable()
	    {
	        base.DeclareScriptVariable();
            textBox.ClientScriptingEnabled=true;
            hidden.ClientScriptingEnabled = true;
            ControlUtil.EnsureIdAttribute(literalButton);
        }

	    protected override IDictionary BuildScriptParameters()
	    {
	        IDictionary parameters =  base.BuildScriptParameters();
	        parameters.Add("id", ClientID);
	        parameters.Add("textBox", textBox.ClientVariable);
	        parameters.Add("buttonId", literalButton.ClientID);
            parameters.Add("hidden", hidden.ClientVariable);
            return parameters;
	        
	    }

        protected override void Bind()
        {
            try
            {
                if (!Configuration.DoBind)
                {
                    Visible = originalVisible;
                    return;
                }

                Visible = Configuration.Visible;

                binder.Bind(new string[] { "Visible", "Enabled", "SelectHoliday" });
                binder.Bind("Value", Configuration.DataTranslator);
                binder.Bind("Text", Configuration.DataTranslator);

                Enabled = Enabled && Configuration.IsEnabledForPrincipal();
                Visible = Visible && Configuration.IsVisibleForPrincipal();
            }
            finally
            {
                if (String.IsNullOrEmpty(Text) && !(Configuration as DatePickerConfiguration).AllowNull)
                    Value = DateTime.Today;
            }
        }

	    protected override void Unbind()
		{
            if (!Configuration.DoUnbind)
                return;
	        
            binder.Unbind("Value", configuration.DataParser);
            binder.Unbind("Text");

            binder.Unbind(new String[] { "Enabled", "Visible" });         
		}
	}
}
